#ifndef __UDP_SERVER_HPP__
#define __UDP_SERVER_HPP__

#include <iostream>
#include <string>
#include <memory>
#include <cstring>
#include <cerrno>
#include <strings.h>
#include <functional>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


#include "Internet.hpp"
#include "Log.hpp"
#include "Common.hpp"
#include "ThreadPool.hpp"

using namespace LogModule;
using namespace ThreadPoolModule;
using adduser_t= std::function<void(InetAddr& user)>;
using task_t = std::function<void()>;
using router_t = std::function<void(int sockfd,const std::string& message)>;
using deluser_t = std::function<void( InetAddr& user)>;


const static  std::string fault_ip = "127.0.0.1";
const static  uint16_t fault_port = 8080;
class UDPServer
{
public:
    UDPServer(uint16_t port = fault_port)
        : _iadr(port), _isrunning(false), _sockfd(-1)
    {
    }
    void Register(adduser_t tadd,router_t route,deluser_t deluser)
    {
        _add = tadd;
        _route = route;
        _del = deluser;
    }
    void InitServer()
    {
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0); //这是创建好了一个网络上的文件
        if (_sockfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket create false";
            Die(USAGE_ERR);
        }
        LOG(LogLevel::INFO) << "socket success, sockfd is : " << _sockfd;

        struct sockaddr_in local;

        int n = bind(_sockfd, _iadr.Addptr(), _iadr.Sizeptr());
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "bind: " << strerror(errno);
            Die(BIND_ERR);
        }
        LOG(LogLevel::INFO) << "bind success";
    }
    void Start()
    {
        LOG(LogLevel::INFO) << "start";
        _isrunning = true;
        while(true)
        {
            //要接受客户端的信息
      

            char inbuffer[1024];
            struct sockaddr_in peer;
           
            socklen_t len = sizeof(peer) ;
            ssize_t n = ::recvfrom ( _sockfd,inbuffer,sizeof(inbuffer)-1,0,CONV(&peer),&len);

            if(n>0)
            {
                
                InetAddr cli(peer);
                inbuffer[n] = 0;
                std::string message;
                if (int sk = strcmp(inbuffer,"QUIT") == 0)
                {
                    // 移除观察者
                    LOG(LogLevel::INFO) <<"走了哦";
                    _del(cli);
                    message = cli.Addr() + "# " + "我走了，你们聊!";
                }
                else
                {
                    // 2. 新增用户
                    std::cout<<inbuffer<< sk <<std::endl;
                    _add(cli);
                    message = cli.Addr() + "####" + inbuffer;
                }

                // 3. 构建转发任务，推送给线程池，让线程池进行转发
                task_t task = std::bind(UDPServer::_route, _sockfd, message);
                ThreadPool<task_t>::getInstance()->Equeue(task);

                //std::string clientinfo = clientip + ":" + std::to_string(clientport) + "#" + inbuffer;
                // std::string clientinfo = inetaddr.IP() + ":" + std::to_string(inetaddr.Port()) + "#" + inbuffer;
                // LOG(LogLevel::DEBUG) << clientinfo;
                //接受消息后 还有给客户端发送数据
                // std::string echo_string = "echo#" ; 
                // echo_string += inbuffer;
                
                // ::sendto(_sockfd,echo_string.c_str(),echo_string.size(),0,CONV(&peer),len);

            }
            else
            {
                 LOG(LogLevel::FATAL) << "recvfrom: " << strerror(errno);
            }
            

        }

    }
    ~UDPServer()
    {
    }

private:
    int _sockfd; // 建立的网络文件描述符
    //std::string _ip;
    //一个服务器可以有多个IP地址，如果将进程绑定到特定的IP上，那只能接收这一个IP发送过来的消息，但是同一个端口有多个IP
    //uint16_t _port;
    InetAddr _iadr;
    bool _isrunning;
    adduser_t _add;
    router_t _route;
    deluser_t _del;
};

#endif